package com.lucenten.collect.gnss.handler.tools.compute;

import lombok.extern.slf4j.Slf4j;

/**
 * 阶乘计算器
 *
 * @author July july_sky@foxmail.com
 * @version 1.0
 * @date 2019/5/4 0:15
 * @Copyright 东方浩星（北京）传媒科技有限公司版权所有.All Rights Reserved.
 */
@Slf4j
public class FactorialCalculator {
    /**
     * 两个一维数组值相加，要求两个数组数量级一致
     *
     * @param source
     * @param plus
     * @return
     */
    public double[] plus(double[] source, double[] plus) {
        if (plus.length < source.length) {
            log.debug("数组数据错误,FactorialCalculator.plus2");
            return source;
        }
        double[] target = new double[source.length];
        for (int i = 0; i < source.length; i++) {
            target[i] = DecimalUtil.add(source[i] , plus[i]);
        }
        return target;
    }

    /**
     * 两个二维数组值相加，要求两个数组数量级一致
     *
     * @param source
     * @param plus
     * @return
     */
    public double[][] plus(double[][] source, double[][] plus) {
        if (plus.length < source.length) {
            log.debug("数组数据错误,FactorialCalculator.plus");
            return source;
        }
        double[][] target = new double[source.length][];
        for (int i = 0; i < source.length; i++) {
            target[i] = this.plus(source[i], plus[i]);
        }
        return target;
    }

    /**
     * 相乘
     *
     * @param source
     * @param multiply
     * @return
     */
    public double[] multiply(double[] source, double multiply) {
        double[] target = new double[source.length];
        for (int i = 0; i < source.length; i++) {
            target[i] = DecimalUtil.mul(source[i], multiply);
        }
        return target;
    }

    /**
     * 相乘
     *
     * @param source
     * @param multiply
     * @return
     */
    public double[][] multiply(double[][] source, double[][] multiply) {
        double[][] target = new double[source.length][];
        for (int row = 0; row < source.length; row++) {
            for (int col = 0; col < multiply[0].length; col++) {
                double num = 0;
                for (int i = 0; i < source[0].length; i++) {
                    num = DecimalUtil.add(num, DecimalUtil.mul(source[row][i], multiply[i][col]));
                }
                target[row][col] = num;
            }
        }
        return target;
    }
    /**
     * 相乘
     *
     * @param source
     * @param multiply
     * @return
     */
    public double[][] multiply(double[][] source, double multiply, int beginRow, int endRow, int beginCol, int endCol) {
        double[][] target = new double[endRow - beginRow][endCol - beginCol];
        for (int i = beginRow; i < endRow; i++) {
            for (int j = beginCol; j < endCol; j ++) {
                target[i - beginRow][j-beginCol] = DecimalUtil.mul(source[i][j], multiply);
            }
        }
        return target;
    }

    /**
     * 所有行列求和
     *
     * @param vals
     * @return
     */
    public double[] sum(double[][] vals) {
        int length = vals[0].length;
        double[] target = new double[length];
        for (double[] val : vals) {
            for (int i = 0; i < length; i ++) {
                target[i] = DecimalUtil.add(target[i],val[i]);
            }
        }
        return target;
    }

    /**
     * 列的乘积
     *
     * @param source
     * @param multiply
     */
    public double[] multiply(double[][] source, double[] multiply) {
        double[] target = new double[source.length];
        double sum = 0;
        for (int i = 0; i < source.length; i ++) {
            sum = 0;
            for (int j = 0; j < source.length; j ++){
                sum = DecimalUtil.add(sum, DecimalUtil.mul(source[i][j], multiply[j]));
            }
            target[i] = sum;
        }
        return target;
    }

    /**
     * 列相加
     *
     * @param vals
     * @param plus
     * @return
     */
    public double[][] plus(double[][] vals, double[] plus) {
        double[][] target = new double[vals.length][plus.length];
        for (int i = 0; i < vals.length; i ++) {
            for (int j = 0; j < plus.length; j ++){
                target[i][j] = DecimalUtil.add(vals[i][j] , plus[j]);
            }
        }
        return target;
    }

    /**
     * 减法
     *
     * @param source
     * @param minus
     * @return
     */
    public double[] minus(double[] source, double[] minus) {
        double[] target = new double[source.length];
        for (int i = 0; i < source.length; i ++) {
            target[i] = source[i] - minus[i];
        }
        return target;
    }
}
